package com.gitee.ixtf.rsocket

import com.gitee.ixtf.rsocket.kotlinx.payload
import io.rsocket.Payload
import io.vertx.core.json.JsonObject
import java.io.Serializable
import kotlinx.coroutines.flow.Flow
import reactor.util.retry.Retry

interface IRSocketRequest : Serializable {
  fun cloudEventType(): String

  suspend fun retry(): Retry? = null

  suspend fun metadataPush(agent: IRSocketAgent, route: String) {
    val buffer = JsonObject.mapFrom(this).toBuffer()
    agent.metadataPush(retry()) {
      agent.cloudEventBuilder().withType(cloudEventType()).withData(buffer.bytes).payload(route)
    }
  }

  suspend fun fireAndForget(agent: IRSocketAgent, route: String) {
    val buffer = JsonObject.mapFrom(this).toBuffer()
    agent.fireAndForget(retry()) {
      agent.cloudEventBuilder().withType(cloudEventType()).withData(buffer.bytes).payload(route)
    }
  }

  suspend fun requestResponse(agent: IRSocketAgent, route: String): Payload {
    val buffer = JsonObject.mapFrom(this).toBuffer()
    return agent.requestResponse(retry()) {
      agent.cloudEventBuilder().withType(cloudEventType()).withData(buffer.bytes).payload(route)
    }
  }

  suspend fun requestStream(agent: IRSocketAgent, route: String): Flow<Payload> {
    val buffer = JsonObject.mapFrom(this).toBuffer()
    return agent.requestStream(retry()) {
      agent.cloudEventBuilder().withType(cloudEventType()).withData(buffer.bytes).payload(route)
    }
  }

  suspend fun requestChannel(agent: IRSocketAgent, route: String): Flow<Payload> = TODO()
}
